﻿using System.Collections.Generic;

namespace winS.Unity
{
    public class RandomPicker<T>
    {
        public int count => itemList.Count;

        public RandomPolicyType policyType { get; set; } = RandomPolicyType.RandomAndNotRepeat;

        private int maxIndex = -1;
        private int lastIndex;

        private readonly List<T> itemList;
        private readonly List<int> indexList;

        public RandomPicker()
        {
            itemList = new List<T>();
            indexList = new List<int>();
        }
        public RandomPicker(RandomPolicyType policyType) : this()
        {
            this.policyType = policyType;
        }
        public RandomPicker(IEnumerable<T> items) : this(items, RandomPolicyType.RandomAndNotRepeat)
        {
        }
        public RandomPicker(IEnumerable<T> items, RandomPolicyType policyType)
        {
            itemList = new List<T>(items);
            maxIndex = itemList.Count - 1;
            indexList = new List<int>(itemList.Count);
            for (int i = 0; i < itemList.Count; i++) indexList.Add(i);
            this.policyType = policyType;
        }

        public void Add(T item)
        {
            itemList.Add(item);
            maxIndex++;
            indexList.Add(maxIndex);
        }

        public T Pick()
        {
            switch (count)
            {
                case 0: throw new System.Exception($"{nameof(RandomPicker<T>)}.{nameof(Pick)}: 没有可Pick的项");
                case 1: return itemList[0];
                default:
                    switch (policyType)
                    {
                        case RandomPolicyType.Order:
                            T result = itemList[indexList[lastIndex]];
                            if (++lastIndex == count) lastIndex %= count;
                            return result;
                        case RandomPolicyType.Random: return itemList[lastIndex = Random.Int(count)];
                        case RandomPolicyType.RandomAndNotRepeat:
                            (indexList[maxIndex], indexList[lastIndex]) = (indexList[lastIndex], indexList[maxIndex]);
                            return itemList[indexList[lastIndex = Random.Int(maxIndex)]];
                        default: throw new System.Exception($"{nameof(RandomPicker<T>)}.{nameof(Pick)}: {policyType}");
                    }
            }
        }
    }
}